package com.gitee.huanminabc.utils_tools.web_base.config;


import com.gitee.huanminabc.jcommon.exception.BizException;
import com.gitee.huanminabc.jcommon.exception.WebException;
import com.gitee.huanminabc.nullchain.Null;
import com.gitee.huanminabc.nullchain.common.NullResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import java.util.List;

// 对全局 Controlle 异常进行处理
@ControllerAdvice
@Slf4j
public class BaseExceptionHandlerConfig {


    /**
     * 处理@Validated参数校验失败异常
     * @param exception 异常类
     * @return 响应
     */
    @ResponseBody
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public NullResult<String> exceptionHandler(MethodArgumentNotValidException exception){
        BindingResult result = exception.getBindingResult();
        if (result.hasErrors()) {
            StringBuilder stringBuilder = new StringBuilder();
            String location = exception.getParameter().getMethod().toString();
            stringBuilder.append("参数校验失败").append("问题接口："+location).append("问题接口参数："+result.getTarget().getClass().getSimpleName());
            List<ObjectError> errors = result.getAllErrors();
            errors.forEach(p -> {
                FieldError fieldError = (FieldError) p;
                stringBuilder.append("[Field：").append(fieldError.getField()).append(", Message：").append(fieldError.getDefaultMessage()).append("]");
            });
            log.error(stringBuilder.toString());
            if (!errors.isEmpty()) {
                ObjectError objectError = errors.get(0);
                FieldError fieldError = (FieldError) objectError;
                //返回第一个就行, 后面的自行看日志或者逐渐处理
                return NullResult.error(Null.orElse(fieldError.getField()+" "+objectError.getDefaultMessage(), ()-> fieldError.getField()+" 校验失败"));
            }
        }
        return NullResult.error(exception.getMessage());
    }

    /**
     * 读取http请求消息失败
     *
     * @param e
     * @return
     */
    @ExceptionHandler({WebException.class})
    @ResponseBody
    public NullResult<Void> webException(WebException e) {
        log.error("",e);
        return NullResult.error(e.getCode(), e.getMessage());
    }

    /**
     * 读取http请求消息失败
     *
     * @param e
     * @return
     */
    @ExceptionHandler({BizException.class})
    @ResponseBody
    public NullResult<Void> httpMessageNotReadable(BizException e) {
        log.error("",e);
        return NullResult.error(e.getMessage());
    }


    @ExceptionHandler(value = RuntimeException.class)
    @ResponseBody
    public NullResult<Void> runtimeException(Exception e) {
        log.error("",e);
        return NullResult.error(e.getMessage());
    }

    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public NullResult<Void> exception(Exception e) {
        log.error("",e);
        return NullResult.error(e.getMessage());
    }

    /**
     * 只要 controller层报错都会被捕捉到 并执行下面代码
     * Exception 异常处理
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = Throwable.class)
    @ResponseBody
    public NullResult<Void> throwable(Exception e) {
        log.error("",e);
        return NullResult.error(e.getMessage());
    }

}
